// ja 实现Ajax并发请求的控制

const delay = interval => {
  return new Promise((res, rej) => {
    setTimeout(res(interval), interval);
    rej('err');
  });
};
const tasks = [() => delay(10000), () => delay(10001), () => delay(10010), () => delay(10100), () => delay(11000)];

const concurrentRequests = () => {
  return Promise.all(tasks.map(task => task())).then(res => {
    // console.log('concurrentRequests res', res)
  });
};

export default concurrentRequests;

// 通过Promise.all实现并行
Promise.all(tasks.map(task => task())).then(res => {
  // console.log(res);
});

// 基于Promise实现
function creatRequest(tasks, pool) {
  // 每次控制的发送请求的数量pool
  pool = pool || 5;
  // 用于存储每一次请求的结果(按顺序进行存贮)
  let results = [],
    // together 用于创建工作区，当pool传入的是几，我们就对应的创建几个工作区
    // 也就是创建一个长度为pool且值为null的一个数组
    together = new Array(pool).fill(null),
    // index为每次获取的任务值
    index = 0;
  together = together.map(() => {
    // 基于Promise进行管理
    return new Promise((resolve, reject) => {
      // 创建一个函数，进来立刻执行
      const run = function run() {
        // 如果任务池已经空了，说明请求发送完成了，直接成功
        if (index >= tasks.length) {
          resolve();
          return;
        }
        // 先将index保存一下用于存储当前成功请求的结果
        let old_index = index,
          // 获取当前发送的请求，然后把index进行累加，所以上面会把index保存起来
          // 这里index++ 是先运算后累加的，而++index则相反，先累加后运算
          task = tasks[index++];
        // 执行请求
        task()
          .then(result => {
            // 将成功结果保存
            results[old_index] = result;
            // 递归继续执行，也就是继续拿到任务到工作区执行
            run();
          })
          .catch(reason => {
            reject(reason);
          });
      };
      // 立即执行
      run();
    });
  });
  // 用Promise.all管控工作区，也就是每次并发两个请求
  return Promise.all(together).then(() => results);
}

creatRequest(tasks, 2)
  .then(results => {
    // 都成功，整体才成功，按顺序存储结果
    // console.log('成功',results);
  })
  .catch(resolve => {
    // 只要有一个失败，整体失败
    console.log('失败');
  });

// 基于Class实现
function classCreatRequest(tasks, pool, callback) {
  // 参数的限制与验证
  if (typeof pool === 'function') {
    callback = pool;
    pool = 5;
  }
  if (typeof pool !== 'number') pool = 5;
  if (typeof callback !== 'function') callback = function () {};
  // -------
  class TaskQueue {
    // 正在运行的个数
    runing = 0;
    // 将所有任务所存在的队列
    queue = [];
    // 存储执行任务(请求)的结果
    results = [];
    pushTask(task) {
      let self = this;
      // 将任务推入工作区
      self.queue.push(task);
      // 执行发送请求的逻辑
      self.next();
    }
    next() {
      let self = this;
      // 当正在执行的任务数小于并发量的时候继续去拿任务执行
      while (self.runing < pool && self.queue.length) {
        self.runing++;
        // 相当于拿一个任务删除一个任务
        let task = self.queue.shift();
        // 执行请求
        task()
          .then(result => {
            // 将执行结果保存
            self.results.push(result);
          })
          .finally(() => {
            // 将正在运行的个数清除
            self.runing--;
            // 继续执行请求
            self.next();
          });
      }
      // 当没有任务了循环结束
      if (self.runing === 0) callback(self.results);
    }
  }
  // 实例化
  let TQ = new TaskQueue();
  tasks.forEach(task => TQ.pushTask(task));
}

classCreatRequest(tasks, 2, results => {
  // console.log(results);
});
